/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.buffer;

import com.inspur.edp.bef.core.session.FuncSession;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.buffer.ICefBuffer;
import com.inspur.edp.cef.api.dataType.base.IAccessorCreator;
import com.inspur.edp.cef.core.buffer.base.BufferManager;
import com.inspur.edp.cef.core.buffer.base.CefBuffer;
import com.inspur.edp.cef.core.manager.EntityDataManager;
import com.inspur.edp.cef.entity.accessor.base.IAccessor;
import com.inspur.edp.cef.entity.accessor.entity.IEntityAccessor;
import com.inspur.edp.cef.entity.changeset.DeleteChangeDetail;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.dependenceTemp.DataValidator;
import com.inspur.edp.cef.entity.entity.IEntityData;
import java.util.HashMap;
import java.util.Map;

//
//     *  0  originalAccessor
//     *  1  transactionAccessor
//     *  2  currentAccessor
//
public class BEBufferManager extends BufferManager
{

	private final static Integer LEVEL_ORIGIN = 0;
	private final static Integer LEVEL_TRANSACTION = 1;
	private final static Integer LEVEL_CURRENT = 2;
	public BEBufferManager(FuncSession session, String entitType, IAccessorCreator accessorCreator)
	{
		super(session, entitType, accessorCreator);
	}


		//region InitBuffer
	public IAccessor createCurrentBuffer(IEntityData data) {return initBufferByLevel(data, LEVEL_CURRENT, false);}

	public IEntityData initTransactionBuffer(String id) {return  (IEntityData)initBufferByBaseLevel(id, LEVEL_TRANSACTION, true);}
	public IEntityData initCurrentBuffer(String id) {return  (IEntityData)initBufferByBaseLevel(id, LEVEL_CURRENT, false);}

		//endregion


		//region getData
	public IEntityData getCurrentData(String dataId){return  (IEntityData)getBuffer(dataId, LEVEL_CURRENT);}

	public IEntityData getTransactionData(String dataId) {return (IEntityData)getBuffer(dataId, LEVEL_TRANSACTION);}

	public IEntityData getOriginalData(String dataId) {return (IEntityData)getBuffer(dataId, LEVEL_ORIGIN);}

		//endregion

		//region Accept/Reject
	public final IAccessor acceptTemplateCurrentChange(String id, IChangeDetail change)
	{
		return acceptChange(id, LEVEL_CURRENT, change);
	}

	public final IAccessor acceptCurrent(String id, IChangeDetail currentChange)
	{
		return accept(id, LEVEL_CURRENT, currentChange);
	}

	public final IAccessor rejectCurrent(String id, IChangeDetail currentChange)
	{
		return reject(id, LEVEL_CURRENT, currentChange);
	}

	public final IAccessor acceptTransaction(String id, IChangeDetail tranChange)
	{
		return accept(id, LEVEL_TRANSACTION, tranChange);
	}

	public final IAccessor rejectTransaction(String id, IChangeDetail tranChange)
	{
		return reject(id, LEVEL_TRANSACTION, tranChange);
	}

	//endregion

	//region atomical rollback
	public IEntityData atomicalRollback4Add(IEntityData data) {
		DataValidator.checkForNullReference(data, "data");
		DataValidator.checkForEmptyString(data.getID(), "data.ID");
		Map<String, Map<Integer, ICefBuffer>> buffers = this.getBuffers(this.getEntityType());
		Map<Integer, ICefBuffer> existing = buffers.get(data.getID());
		if(existing == null) {
			existing = new HashMap<>(4);
			buffers.put(data.getID(), existing);
		}
		existing.put(LEVEL_TRANSACTION, new CefBuffer((IAccessor)data));
		RefObject<IEntityData> sourceRef = new RefObject<>(null);
		//TODO:直接createAccessor()现只适用没有变更的情况下构造各层buffer, 有子表变更时会丢失子表, 借用EntityDataManager实现带变更的buffer构造
		EntityDataManager.getInstance().rejectChanges(
				getAccessorCreator(), sourceRef, data, new DeleteChangeDetail(data.getID()), false);
		existing.put(LEVEL_CURRENT, new CefBuffer((IAccessor) sourceRef.argvalue));
		return (IEntityAccessor) sourceRef.argvalue;
	}
	//endregion
}
